Model.js ➔ ???   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3.2098

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 3
c 4
b 0
f 0
nc 4
dl 0
loc 13
ccs 5
cts 7
cp 0.7143
crap 3.2098
rs 9.4285
nop 2

1 Function

Rating   Name   Duplication   Size   Complexity  
A Model.js ➔ ... ➔ ??? 0 1 1
1
/**
2
 * Abstract Model class interacting with MongoDB
3
 *
4
 * @since 1.0.0
5
 */
6
7 4
const co = require('co');
8 4
const mongodb = require('mongodb');
9 4
const config = require('../config/server.config');
10 4
const NotifierError = require('../common/Error');
11
12 4
const MongoClient = mongodb.MongoClient;
13 4
const ObjectID = mongodb.ObjectID;
14 4
const url = process.env.MONGODB_URI || config.defaults.mongoDBUrl;
15 4
const logger = require('winston');
16
17
/**
18
 * @class
19
 * @classdesc basic interactions with selected collection
20
 */
21
class Model {
22
23
  constructor(collection, indexes) {
24 16
    if (new.target === Model) {
25
      throw new TypeError('Cannot construct Model instances directly');
26
    }
27
28 16
    this.collection = collection || this.constructor.name.toLowerCase();
29
30 16
    if (indexes instanceof Array) {
31 16
      this.runQuery(col => col.createIndexes(indexes))
32 16
        .then(() => logger.log(`[DB] ${this.collection}'s index creation is successfully done.`))
33
        .catch(error => logger.error(`[DB] ${this.collection}'s index creation is failed.`, error));
34
    }
35
  }
36
37
  runQuery(fn) {
38 107
    const self = this;
39 107
    return co(function* () {
40 107
      const db = yield MongoClient.connect(url);
41 107
      const collection = db.collection(self.collection);
42 107
      const result = yield fn.call(self, collection);
43 107
      yield db.close();
44 107
      return result;
45
    }).catch((err) => {
46
      throw err;
47
    });
48
  }
49
50
  find(query, sort, skip, limit) {
51 26
    if (query && query._id) {
52 8
      query._id = ObjectID(query._id);
53
    }
54 26
    return this.runQuery((collection) => {
55 26
      const cursor = collection.find(query || {}).sort(sort || {});
56 26
      if (typeof skip !== 'undefined' || typeof limit !== 'undefined') {
57
        cursor.skip(skip).limit(limit);
58
      }
59 26
      return cursor.toArray();
60 26
    }).then(list => list.map((item) => {
61 37
      item._id = item._id.toHexString();
62 37
      return item;
63
    })).catch((error) => {
64
      logger.error(error);
65
      throw new NotifierError(NotifierError.Types.DB, {}, error);
66
    });
67
  }
68
69
  count(query) {
70 12
    return this.runQuery(collection => collection.count(query || {}))
71
      .catch((error) => {
72
        logger.error(error);
73
        throw new NotifierError(NotifierError.Types.DB, {}, error);
74
      });
75
  }
76
77
  add(model) {
78 26
    return this.runQuery(collection => collection.insertOne(model))
79
      .then((result) => {
80 26
        let data = result.ops;
81 26
        if (data) {
82 26
          data = result.ops.map(d => Object.assign({}, d, { _id: d._id.toHexString() }));
83
        }
84 26
        return { data, count: result.result.n };
85
      })
86
      .catch((error) => {
87
        logger.error(error);
88
        throw new NotifierError(NotifierError.Types.DB, {}, error);
89
      });
90
  }
91
92
  update(id, model, unset) {
93 8
    return this.updateWithQuery({ _id: ObjectID(id) }, model, unset);
94
  }
95
96
  updateWithQuery(query, model, unset) {
97 9
    const option = { $set: model };
98 9
    if (unset) {
99 3
      option.$unset = unset;
100
    }
101 9
    return this.runQuery(collection => collection.findOneAndUpdate(query, option))
102
103 9
      .then(result => ({ data: [{ _id: result.value._id.toHexString() }], count: 1 }))
104
      .catch((error) => {
105
        logger.error(error);
106
        throw new NotifierError(NotifierError.Types.DB, {}, error);
107
      });
108
  }
109
110
  remove(id) {
111 18
    return this.runQuery(collection => collection.deleteOne({ _id: ObjectID(id) }))
112 18
      .then(result => ({ data: [{ _id: id }], count: result.result.n }))
113
      .catch((error) => {
114
        logger.error(error);
115
        throw new NotifierError(NotifierError.Types.DB, {}, error);
116
      });
117
  }
118
}
119
120
module.exports = Model;
121